package edu.study.api.common.json;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import edu.study.api.common.sensitive.SensitiveUtil;
import org.apache.commons.lang.StringUtils;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

public class JsonUtils {

	public static ObjectMapper objectMapper = new ObjectMapper();

	static {
		objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
		// objectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
		objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
		objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		objectMapper.configure(com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
		DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		objectMapper.setDateFormat(df);
	}

	/**
	 * fromJson
	 *
	 * @return
	 */
	public static <T> T fromJson(String json, Class<T> clazz) {
		if (StringUtils.isEmpty(json)) {
			return null;
		}
		try {
			return objectMapper.readValue(json, clazz);
		} catch (JsonParseException e) {
			throw new RuntimeException("from json failed", e);
		} catch (JsonMappingException e) {
			throw new RuntimeException("from json failed", e);
		} catch (IOException e) {
			throw new RuntimeException("from json failed", e);
		}
	}

	public static <T> T fromJson(String json, TypeReference<T> typeRef) {
		if (StringUtils.isEmpty(json)) {
			return null;
		}
		try {
			return objectMapper.readValue(json, typeRef);
		} catch (JsonParseException e) {
			throw new RuntimeException("from json failed", e);
		} catch (JsonMappingException e) {
			throw new RuntimeException("from json failed", e);
		} catch (IOException e) {
			throw new RuntimeException("from json failed", e);
		}
	}

	/**
	 * @param object
	 * @return
	 */
	public static String toJson(Object object) {
		if (object == null) {
			return null;
		}
		try {
			Object jsonIgnoreObject = JsonIgnoreFieldUtil.jsonIgnoreObject(object);
			String json = objectMapper.writeValueAsString(jsonIgnoreObject);
			return json;
		} catch (JsonProcessingException e) {
			throw new RuntimeException("to toJson fields masked json failed", e);
		}
	}

	/**
	 * @param object
	 * @return
	 */
	public static String toInsensitiveJson(Object object) {
		if (object == null) {
			return null;
		}
		try {
			Object sensitiveObject = SensitiveUtil.sensitiveObject(object);
			String json = objectMapper.writeValueAsString(sensitiveObject);
			return json;
		} catch (JsonProcessingException e) {
			throw new RuntimeException("to toInsensitiveJson fields masked json failed", e);
		}
	}
}
